/***************************************************************************
 *            voce.h
 *
 *  ven giugno 10 09:47:56 2011
 *  Copyright  2011, 2012  Massimiliano Maniscalco
 *  <massi.neptune@yahoo.com>
 ****************************************************************************/
/*
 * voce.h
 *
 * Copyright (C) 2011, 2012 - Massimiliano Maniscalco
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _VOCE_H_
#define _VOCE_H_

#include <gtkmm.h>
#include <iostream>
#include <iomanip>
#include <cassert>

using namespace std;

class Voce
{
public:
	inline ~Voce();
	inline void set_contesto ( const Glib::ustring &str ) { _contesto.assign ( str ); }
	inline void set_contesto ( const char *cstr );
	inline Glib::ustring get_contesto ( void ) const { return _contesto; }
	inline void set_valutazione ( unsigned short index, char val );
	inline void set_valutazione ( unsigned short index, const char *cstr );
	inline char get_valutazione ( unsigned short index ) const;
	inline void set_data_esame ( unsigned short index, time_t data );
	inline void set_data_esame ( unsigned short index, struct tm * timeptr );
	inline time_t get_data_esame ( unsigned short index ) const;
	inline Glib::ustring get_string_data_esame ( unsigned short index ) const;
	inline void set_test_svolti ( unsigned int val ) { _testSvolti = val; }
	inline void set_test_svolti ( const char *cstr ) { _testSvolti = atoi ( cstr ); }
	inline unsigned int get_test_svolti ( void ) const { return _testSvolti; }
	inline void set_errata ( bool flag ) { _errata = flag; }
	inline bool get_errata ( void ) const { return _errata; }
	inline void test ( unsigned short index, bool result, int tempo );
	inline void reset_stats ( void );
	inline Glib::ustring get_voce_xml ( void ) const;
	
protected:
	Voce() : _contesto ( "" ), _testSvolti ( 0 ), _errata ( false )
	{
		_valutazione = new char[ _numeroTest ];
		_dataEsame = new time_t[ _numeroTest ];
		for ( unsigned char n = 0; n < _numeroTest; n++ )
		{
			*(_valutazione + n) = 0;
			*(_dataEsame + n) = 0.0;
		}
	}
	Glib::ustring _contesto;
	static const unsigned short _numeroTest = 4;
	char *_valutazione;
	time_t *_dataEsame;
	unsigned int _testSvolti;
	bool _errata;
};

inline Voce::
~Voce ()
{
	delete[] _valutazione;
	delete[] _dataEsame;
}

inline void Voce::
set_contesto ( const char *cstr )
{
	if ( cstr )
		_contesto.assign ( cstr );
}

inline void Voce::
set_valutazione ( unsigned short index, char val )
{
	assert(index >= 0 && index < _numeroTest);
	char *pv = _valutazione + index;
	*pv = val;
}

inline void Voce::
set_valutazione ( unsigned short index, const char *cstr )
{
	assert(index >= 0 && index < _numeroTest);
	char *pv = _valutazione + index;
	*pv = atoi ( cstr );
}

inline char Voce::
get_valutazione ( unsigned short index ) const
{
	assert(index >= 0 && index < _numeroTest);
	char *pv = _valutazione + index;
	return *pv;
}

inline void Voce::
set_data_esame ( unsigned short index, time_t data )
{
	assert(index >= 0 && index < _numeroTest);
	time_t *pt = _dataEsame + index;
	*pt = data;
}

inline void Voce::
set_data_esame ( unsigned short index, struct tm * timeptr )
{
	assert(index >= 0 && index < _numeroTest);
	time_t *pt = _dataEsame + index;
	*pt = mktime ( timeptr );
}

inline time_t Voce::
get_data_esame ( unsigned short index ) const
{
	assert(index >= 0 && index < _numeroTest);
	time_t *pt = _dataEsame + index;
	return *pt;
}

inline Glib::ustring Voce::
get_string_data_esame ( unsigned short index ) const
{
	Glib::ustring str;
	struct tm *dataOra;
	time_t rawTime = get_data_esame ( index );
	dataOra = localtime ( &rawTime );
	str.append ( Glib::ustring::compose ( "%1:%2:%3 %4/%5/%6", Glib::ustring::format ( setfill(L'0'), setw(2), dataOra->tm_hour ), Glib::ustring::format ( setfill(L'0'), setw(2), dataOra->tm_min ), Glib::ustring::format ( setfill(L'0'), setw(2), dataOra->tm_sec ), Glib::ustring::format ( setfill(L'0'), setw(2), dataOra->tm_mday ), Glib::ustring::format ( setfill(L'0'), setw(2), dataOra->tm_mon + 1 ), Glib::ustring::format ( setfill(L'0'), setw(4), dataOra->tm_year + 1900 ) ) );
	return str;
}

inline void Voce::
test ( unsigned short index, bool result, int tempo )
{
	char voto;
	char votoPrecedente = get_valutazione ( index );
	time_t esamePrecedente = get_data_esame ( index );
	time_t adesso = time ( NULL );
	double tempoTrascorso = difftime ( adesso, esamePrecedente );
	if ( result )
	{
		if ( tempo < 6 )
			voto = 8;
		if ( tempo > 4 && tempo < 11 )
			voto = 7;
		if ( tempo > 10 && tempo < 16 )
			voto = 6;
		if ( tempo > 15 && tempo < 21 )
			voto = 5;
		if ( tempo > 20 )
			voto = 4;
		if ( voto > votoPrecedente )
		{
			if ( tempoTrascorso < 604800 && ( voto - votoPrecedente ) > 1 )	// meno di una settimana
				voto--;
			if ( tempoTrascorso > 1209600 && tempoTrascorso < 2592000 )	// piu' di due settimane ma meno di un mese
				voto++;
			if ( tempoTrascorso > 2592000 )	// piu' di un mese
				voto += 2;
		}
		if ( voto < votoPrecedente )
		{
			if ( tempoTrascorso < 604800 && ( votoPrecedente - voto ) < 2 )	// meno di una settimana
				voto--;
			if ( tempoTrascorso > 2592000 && ( votoPrecedente - voto ) > 1 )	// piu' di un mese
				voto++;
		}
		if ( voto == votoPrecedente )
		{
			if ( tempoTrascorso > 2592000 && voto < 8 )	// piu' di un mese
				voto++;
		}
	}
	else
	{
		voto = votoPrecedente - 1;
		if ( tempoTrascorso < 604800 && voto > 6 )	// meno di una settimana
			voto--;
		if ( tempoTrascorso > 2592000 && voto > 6)	// piu' di un mese
			voto++;
	}
	if ( voto < 0 )
		voto = 0;
	if ( voto > 10 )
		voto = 10;
	set_data_esame ( index, adesso );
	set_valutazione ( index, voto );
	set_errata ( !result );
	_testSvolti++;
}

inline void Voce::
reset_stats ( void )
{
	for ( unsigned char n = 0; n < _numeroTest; n++ )
	{
		*(_valutazione + n) = 0;
		*(_dataEsame + n) = 0.0;
	}
	_testSvolti = 0;
}

inline Glib::ustring Voce::
get_voce_xml ( void ) const
{
	Glib::ustring str;
	str.append ( Glib::ustring ( "\t<contesto>" + _contesto + "</contesto>\n" ) );
	if ( _testSvolti > 0 )
	{
		str.append ( Glib::ustring ( "\t<testSvolti>" + Glib::ustring::format ( _testSvolti ) + "</testSvolti>\n" ) );
		str.append ( Glib::ustring ( "\t<risultati>\n" ) );
		for ( unsigned char n = 0; n < _numeroTest; n++ )
		{
			if ( *(_dataEsame + n) > 0 )
			{
				struct tm *dataOra;
				dataOra = localtime ( (_dataEsame + n) );
				str.append ( Glib::ustring ( "\t\t<indice>" + Glib::ustring::format ( n ) + "</indice>\n" ) );
				str.append ( Glib::ustring ( "\t\t<valutazione>" + Glib::ustring::format ( static_cast<int>( *(_valutazione + n) ) ) + "</valutazione>\n" ) );
				str.append ( Glib::ustring ( "\t\t<data>" + Glib::ustring::compose ( "%1-%2-%3", Glib::ustring::format ( setfill(L'0'), setw(4), dataOra->tm_year + 1900 ), Glib::ustring::format ( setfill(L'0'), setw(2), dataOra->tm_mon + 1 ), Glib::ustring::format ( setfill(L'0'), setw(2), dataOra->tm_mday ) ) + "</data>\n" ) );
				str.append ( Glib::ustring ( "\t\t<ora>" + Glib::ustring::compose ( "%1:%2:%3", Glib::ustring::format ( setfill(L'0'), setw(2), dataOra->tm_hour ), Glib::ustring::format ( setfill(L'0'), setw(2), dataOra->tm_min ), Glib::ustring::format ( setfill(L'0'), setw(2), dataOra->tm_sec ) ) + "</ora>\n" ) );
			}
		}
		str.append ( Glib::ustring ( "\t</risultati>\n" ) );
	}
	return str;
}

#endif // _VOCE_H_
